Two distinct design philosophies currently define how autonomous intelligent systems engage with the world: AI agents and agentic AI. The terms are similar, but they represent technologies with different attributes. The purpose of this introductory post is to distinguish between AI agents and agentic AI, introduce use cases from business and academia, and explore just a few of the ethical and practical consequences of implementing agentic systems. At the end I'll leave you with lots of resources that I am finding helpful in navigating this topic.
Hello,
We have a requirement in our SAS Viya environment where only a limited set of groups ( mainly SAS administrator ) should be able to schedule jobs through SAS Studio or SAS Environment Manager.
I tried modifying the authorization rules in SAS Environment Manager for the /scheduler and /SASjobexecution object URIs. Instead of granting permissions to the Authenticated Users group, I granted permissions only to the SAS Administrators group. However, non SAS Admin users are still able to schedule jobs through SAS Studio.
Could you please let me know the complete list of object URIs that need to be restricted to control job scheduling access for specific groups?
Thanks in advance.
... View more
Hello everyone, I am trying to install the local version of SAS, but the installation always gets stuck at the second step related to the Deployment Manager. However, I followed the instructions carefully,but it still does not work. I am using Windows 11 and my license is valid. Has anyone experienced this issue or has a solution? Thank you in advance for your help.
... View more
I use the SAS Extension for Visual Studio Code for projects that also involve a mix of Python, with Python projects containing different configuration, version specifications, and package dependencies. I find installing and maintaining those artifacts cumbersome and error-prone.
Over time, I have developed practices that suit my working style and yield organisation, isolation and automation benefits. I execute them through a shell script which I call my “build” script. Here’s an outline.
Organisation
I have been using a Mac laptop for a long time and store several projects under a central folder called current_projects . That’s a bit of a misnomer because I am not very meticulous about archiving my folders so you find everything there happens to be “current”. Within each folder is a build folder. The purpose of this build folder is to:
Hold a shell script (details follow) which executes the “build” activity
Serve as a parent folder to any virtual (Python) environments I may choose to create
Store configuration and other variables about the project build, such as a .env file.
The idea is to implement a “boring consistency”. I expect to find a build folder in every project folder I open and can trigger the same so that I can develop with the most relevant configuration.
current_projects - project1 - build - build.sh - requirements.txt - project2 - build - build.sh - requirements.txt - projectN - build - build.sh - requirements.txt
Isolation
Projects utilise several distinct packages, some of which require a specific Python version. Attempting to install and maintain all packages in my base Python environment is foolhardy and will likely result in version and dependency conflicts. Virtual environments are useful in such situations because they help me package my solution specifications in a portable, reusable and repeatable manner. My typical build.sh contains the following.
#!/usr/bin/env bash set -euo pipefail # Create and activate virtual environment python -m venv buildproj . buildproj/bin/activate # Upgrade pip python -m pip install --upgrade pip # install uv, a fast Python package manager pip install --upgrade uv # Use uv to install from requirements.txt uv pip install -r requirements.txt --force-reinstall --upgrade # I find it easy to work with Jupyter notebooks and so attach my venv kernel to ipykernel to surface the same in Jupyter python -m ipykernel install --user --name=buildproj # If I want to run some automated scripts after installing the virtual env, now is the opportunity. # python scripts/ # I activate the environment upon need so deactivate the venv for now. deactivate # I keep the below commented during development and use only for test runs or for cleanup after an automated script. # rm -rf buildproj
Some points to note from the above script.
I prefer uv as a Python package manager due to its faster speed compared to the standard pip utility.
During development, I tend towards ephemeral environments where I build the virtual environment afresh every time I work on the project. Your preference may vary. Once I am done with development, I run this script only to execute some prepared programs ( the commented python scripts/ section) and then remove the folder altogether. Saves some space.
I use jupyter-lab . To ensure my notebook accesses the right Python kernel (i.e. the one associated with the virtual environment), I use ipykernel to install a kernel pointing to the venv I created.
This way, irrespective of where I choose to develop, my configuration travels with my code. I can push my project to a GitHub repository, clone it from another machine (assuming I have Python of the same version installed) and run the build.sh script to create my virtual environment afresh.
Automation
While convenient, I’d like it even better were I not be required to remember to run this script every time I open a project. Visual Studio Code’s automation capabilities, offered through tasks, come in useful. Here’s what I need to consider when opening a project.
The virtual environment from the last time I worked on this project might still be lingering about.
Temporary folders such as __pycache__ and .ipynb_checkpoints from my previous development session need to be cleaned up.
A brainwave during the night might entail adding new packages to requirements.txt
And, of course, I need to remember to run the build script
These folders aren’t trivial and, depending on the size and number of projects, take up space on my workstation. I’d prefer to not even have my projects sit in my workstation anyways, isn’t that what GitHub is for?
Tasks help you automate routine activities in Visual Studio Code. Tasks can be folder-specific or workspace-specific and can call additional scripts upon certain triggers (such as opening a folder for instance). Tasks can also be sequenced.
Create a Python program which resides in a scripts folder in your project (you may choose to even have this reside in build but I like to keep them separate). An example is shown here.
from pathlib import Path import shutil root = Path(__file__).resolve().parents[1] delete_dirs = {"__pycache__", ".ipynb_checkpoints", ".pytest_cache", "buildproj", "node_modules"} delete_files = {".DS_Store"} for path in root.rglob("*"): if path.is_dir() and path.name in delete_dirs: shutil.rmtree(path, ignore_errors=True) elif path.is_file(): if path.name in delete_files or path.suffix == ".pyc": try: path.unlink() except FileNotFoundError: pass
This program searches for specified directories and files anywhere within the repository and deletes them. I have included common files which I do not require (since I shall probably be recreating them as I develop).
Next, create a folder called .vscode (it may already exist) in the root folder of your project and add a tasks.json there. If a tasks.json exists, it’s possible that you already know how to define a task and in this case, would be adding one more. Here’s the block to add to your tasks.json .
{ "version": "2.0.0", "tasks": [ { "label": "Clean Python cache", "type": "shell", "command": "python", "args": [ "${workspaceFolder}/scripts/clean_cache.py" ], "runOptions": { "runOn": "folderOpen" }, "presentation": { "reveal": "never", "panel": "shared" }, "problemMatcher": [] } ] }
This is only the first task. Simply expressed, it runs every time this folder ( ${workspaceFolder} ) is opened and executes a Python program (the one above) that cleans up unwanted folders and files. Tasks can also be configured through the command palette of Visual Studio Code.
The second task, which you would ideally want to have run after the first task is as follows. This may also be added to the tasks list in the tasks.json file above.
{ "label": "build_environment", "type": "shell", "command": "cd build && ./build.sh", "args": [ ], "dependsOn": "Clean Python cache", "dependsOrder": "sequence", "runOptions": { "runOn": "folderOpen" }, "presentation": { "reveal": "always", "panel": "shared" }, "problemMatcher": [] }
Once you’ve deleted unwanted files and folders, you can proceed with building the environment afresh. Note the additional options here: dependsOn and dependsOrder . dependsOn specifies that the build_environment task depends on the successful run of the Clean Python cache task. dependsOrder specifies that this should run in sequence, i.e. after Clean Python cache . The final tasks.json is as follows.
{ "version": "2.0.0", "tasks": [ { "label": "Clean Python cache", "type": "shell", "command": "python", "args": [ "${workspaceFolder}/scripts/clean_cache.py" ], "runOptions": { "runOn": "folderOpen" }, "presentation": { "reveal": "never", "panel": "shared" }, "problemMatcher": [] }, { "label": "build_environment", "type": "shell", "command": "cd build && ./build.sh", "args": [ ], "dependsOn": "Clean Python cache", "dependsOrder": "sequence", "runOptions": { "runOn": "folderOpen" }, "presentation": { "reveal": "always", "panel": "shared" }, "problemMatcher": [] } ] }
Test this by closing (File -> Close Folder) and then reopening the project folder. Be prepared to show a little patience the first time as waiting for the task to complete may take some getting used to.
Be aware of the tradeoffs. Depending on their complexity, tasks may run for some time and you may need to wait a short while after opening the folder to commence your work. Also, some projects with complex dependencies and heavy packages might be better off left alone without having to rebuild them every time. Your configuration is a carefully crafted context-contingent choice.
Creating a build script enables rapid experimentation and development and provides you repeatability and portability benefits. For a starter script, refer this GitHub repository and feel free to provide your suggestions in the comments section.
GitHub repository: https://github.com/SundareshSankaran/build-script
... View more
Hi may I suggest that for Macro1 lesson practice m104p05, the example of local macro, the name of the macro, scope, is very confusing (and it is good to use other name for the macro), I spent about 1 hour on it and finally figured out what was the issue that confused me. The code is as follows:
%macro scope;
%let stormtype1=Some damage;
%let stormtype2=Extensive damage;
%let stormtype3=Devastating damage;
%let stormtype4=Catastrophic damage;
%let stormtype5=Widespread catastrophic damage;
%put _user_;
%mend scope;
%scope;
After run the code, the log is as follows:
69 %macro scope;
70 %let stormtype1=Some damage;
71 %let stormtype2=Extensive damage;
72 %let stormtype3=Devastating damage;
73 %let stormtype4=Catastrophic damage;
74 %let stormtype5=Widespread catastrophic damage;
75 %put _user_;
76 %mend scope;
77 %scope;
SCOPE STORMTYPE1 Some damage
SCOPE STORMTYPE2 Extensive damage
SCOPE STORMTYPE3 Devastating damage
SCOPE STORMTYPE4 Catastrophic damage
SCOPE STORMTYPE5 Widespread catastrophic damage
GLOBAL GRAPHINIT GOPTIONS RESET=ALL GSFNAME=_GSFNAME;
GLOBAL GRAPHTERM GOPTIONS NOACCESSIBLE;
Seeing the log I had an wrong impression that global macro is explicitly displayed in the log as GLOBAL ones and local macro is explicitly displayed in the log as SCOPE ones, and I even tried at least 6 to 10 times to use %put _scope_; and %put _local_; to display my local macros in the log but failed, until I somehow luckily tried the follows:
%macro test;
%global stormtype1;
%let stormtype1=Some damage;
%let stormtype2=Extensive damage;
%let stormtype3=Devastating damage;
%let stormtype4=Catastrophic damage;
%let stormtype5=Widespread catastrophic damage;
%put _user_;
%mend test;
%test;
And get this log as follows, and then I had the correct concepts, that is:
(a) unlike global macros displayed in the log as GLOBAL ones, local macro is NOT explicitly displayed in the log as something like LOCAL ones or SCOPE ones, it is the macro name TEST,
(b) if I want to display local macros in the log, I have to use %put _user_; inside the macro, if I use %put _user_; or %put _all_; outside this macro, then only global and automatic macros are displayed, local macros are not displayed, and
(c) so there is a question, is there any statement (aside from, for example, like %put &stormtype1;) I can use here, outside the %macro test macro, to display all of the local macro only (and do not display the global and automatic ones)?
69 %macro test;
70 %global stormtype1;
71 %let stormtype1=Some damage;
72 %let stormtype2=Extensive damage;
73 %let stormtype3=Devastating damage;
74 %let stormtype4=Catastrophic damage;
75 %let stormtype5=Widespread catastrophic damage;
76 %put _user_;
77 %mend test;
78 %test;
TEST STORMTYPE2 Extensive damage
TEST STORMTYPE3 Devastating damage
TEST STORMTYPE4 Catastrophic damage
TEST STORMTYPE5 Widespread catastrophic damage
GLOBAL GRAPHINIT GOPTIONS RESET=ALL GSFNAME=_GSFNAME;
GLOBAL GRAPHTERM GOPTIONS NOACCESSIBLE;
GLOBAL STORMTYPE1 Some damage
Another thought is: use %global statement very carefully because it is very easily to get macros confused created in the session.
... View more